package com.xb.cloud.merchantapi.product.service.impl;

import java.util.Date;
import java.util.HashMap;
import java.util.Map;

import javax.annotation.Resource;

import org.apache.commons.codec.digest.DigestUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;

import com.xb.cloud.common.JsonUtils;
import com.xb.cloud.common.constant.DbConstants;
import com.xb.cloud.common.redis.CacheUtil;
import com.xb.cloud.common.sms.SmsSender;
import com.xb.cloud.common.sms.VerifyCode;
import com.xb.cloud.common.util.DateUtils;
import com.xb.cloud.common.util.RSAUtils;
import com.xb.cloud.common.util.StringUtils;
import com.xb.cloud.common.util.UUidUtils;
import com.xb.cloud.gateway.client.ReturnCodes;
import com.xb.cloud.gateway.client.ReturnUtils;
import com.xb.cloud.gateway.client.RtnInfo;
import com.xb.cloud.merchantapi.config.AppConfig;
import com.xb.cloud.merchantapi.product.service.EndMerchantPassportUserService;
import com.xb.cloud.product.merchant.service.client.EndMerchantUserService;
import com.xb.cloud.product.merchant.service.client.MerchantSmsSendLogService;
import com.xb.cloud.product.merchant.service.client.MerchantUserAutoLoginService;
import com.xb.cloud.product.merchant.service.client.bo.EndMerchantUserBo;
import com.xb.cloud.product.merchant.service.client.bo.MerchantUserAutoLoginBo;
import com.xb.cloud.product.merchant.service.client.bo.SmsSendLogBo;
import com.xb.cloud.service.client.ServiceReturnInfo;
import com.xb.cloud.service.client.ServiceReturnUtils;

/**
 * 
 * @ClassName: MerchantapiServiceImpl
 * @Description:TODO
 * @author: 鲜备科技
 * @date: 2018年3月2日 上午10:39:34
 * 
 * @Copyright: 2018 www.xianbeitech.com Inc. All rights reserved.
 *
 */
@Service
public class EndMerchantPassportUserServiceImpl implements EndMerchantPassportUserService {
	private static final Logger LOGGER = LoggerFactory.getLogger(EndMerchantPassportUserService.class);

	@Resource
	EndMerchantUserService endMerchantUserService;

	@Resource
	MerchantPassportServiceValidator validator;
	// TODO:修改名称

	@Resource
	MerchantUserAutoLoginService merchantUserAutoLoginService;

	@Resource
	MerchantSmsSendLogService MerchantsmsSendLogService;

	@Resource
	SmsSender smsSender;

	@Override
	public RtnInfo loginWithPassword(long companyId, String phoneNum, String password) {
		// TODO: 数据库记录
		try {
			password = RSAUtils.decryptStr(password);
		} catch (Exception e) {
			return ReturnUtils.error(ReturnCodes.PASSWORD_DECRYPT_ERROR);
		}

		RtnInfo rtnInfo = validator.validPhoneWithPassword(phoneNum, password);
		if (ReturnUtils.isError(rtnInfo)) {
			return rtnInfo;
		}

		EndMerchantUserBo merchantUserBo = null;
		ServiceReturnInfo returnInfo = endMerchantUserService.getEndMerchantUserByPhoneNum(companyId, phoneNum);
		if (ServiceReturnUtils.isSuccess(returnInfo)) {
			if (returnInfo.getData() == null) {
				return ReturnUtils.error(ReturnCodes.PHONENUM_OR_PASSWORD_ERROR);
			}
			merchantUserBo = (EndMerchantUserBo) returnInfo.getData();
		} else {
			return ReturnUtils.error(ReturnCodes.SYSTEM_EXCEPTION);
		}

		String pwd = DigestUtils.md5Hex(password);
		String merchantUserBoPassword = merchantUserBo.getPassword();

		if (!pwd.equals(merchantUserBoPassword)) {
			return ReturnUtils.error(ReturnCodes.PHONENUM_OR_PASSWORD_ERROR);
		}

		Map<String, Object> resultMap = generateTokens(merchantUserBo);

		return ReturnUtils.success(resultMap);
	}

	@Override
	public RtnInfo logout(String userToken, String autoUserToken) {
		String tokenKey = String.format(AppConfig.MERCHANTUSERTOKEN_KEY, userToken);
		if (CacheUtil.exists(tokenKey)) {
			CacheUtil.del(tokenKey);
		}
		merchantUserAutoLoginService.deleteByAut(autoUserToken);
		return ReturnUtils.success();
	}

	@Override
	public RtnInfo autoLogin(String autoUserToken) {
		if (StringUtils.isEmpty(autoUserToken)) {
			return ReturnUtils.error(ReturnCodes.AUTO_USER_TOKEN_REQUIRED);
		}

		MerchantUserAutoLoginBo merthantUserAutoLoginBo = null;
		ServiceReturnInfo serviceReturnInfo = merchantUserAutoLoginService.getByAut(autoUserToken);
		if (ServiceReturnUtils.isSuccess(serviceReturnInfo)) {
			if (serviceReturnInfo.getData() != null) {
				merthantUserAutoLoginBo = (MerchantUserAutoLoginBo) serviceReturnInfo.getData();
			}
		}

		if (merthantUserAutoLoginBo == null) {
			return ReturnUtils.error(ReturnCodes.AUTO_USER_TOKEN_INVALID);
		}

		Date currentDate = new Date();
		Date expireTime = merthantUserAutoLoginBo.getExpireTime();
		if (DateUtils.compare(expireTime, currentDate) > 0) {
			// autoUserToken未过期
			Long merchantUserId = merthantUserAutoLoginBo.getAdminUserId();

			EndMerchantUserBo merchantUserBo = null;
			ServiceReturnInfo returnInfo = endMerchantUserService.getEndMerchantUserById(merchantUserId);
			if (ServiceReturnUtils.isSuccess(returnInfo)) {
				if (returnInfo.getData() == null) {
					return ReturnUtils.error(ReturnCodes.USER_NOT_EXIST);
				} else {
					merchantUserBo = (EndMerchantUserBo) returnInfo.getData();
				}
			} else {
				return ReturnUtils.error(ReturnCodes.SYSTEM_EXCEPTION);
			}
			merchantUserBo.setAdminUserLastLoginDate(currentDate);

			String userToken = UUidUtils.getUUID();
			String tokenKey = String.format(AppConfig.MERCHANTUSERTOKEN_KEY, userToken);
			CacheUtil.setex(tokenKey, AppConfig.EXPIRE_MERCHANTUSERTOKEN_MINUTE_60, merchantUserBo);

			Map<String, Object> resultMap = new HashMap<String, Object>();
			resultMap.put("userToken", userToken);
			resultMap.put("autoUserToken", autoUserToken);

			return ReturnUtils.success(resultMap);
		} else {
			// 已过期，需要重新登录
			ServiceReturnInfo returnInfo = merchantUserAutoLoginService.deleteAutoLogin(merthantUserAutoLoginBo);
			if (ServiceReturnUtils.isError(returnInfo)) {
				LOGGER.error("auto UserToken 删除失败");
			}
			return ReturnUtils.error(ReturnCodes.AUTO_USER_TOKEN_INVALID);
		}
	}

	@Override
	public RtnInfo resetPassword(long companyId, String phoneNum, String verifyCode, String password) {
		try {
			password = RSAUtils.decryptStr(password);
		} catch (Exception e) {
			return ReturnUtils.error(ReturnCodes.PASSWORD_DECRYPT_ERROR);
		}

		RtnInfo rtnInfo = validator.validPhoneWithPassword(phoneNum, password);
		if (ReturnUtils.isError(rtnInfo)) {
			return rtnInfo;
		} else {

			// 验证验证码是否相等
			rtnInfo = checkVerifyCode(companyId, phoneNum, verifyCode);
			if (ReturnUtils.isError(rtnInfo)) {
				return rtnInfo;
			}
		}

		EndMerchantUserBo merchantUserBo = null;
		ServiceReturnInfo returnInfo = endMerchantUserService.getEndMerchantUserByPhoneNum(companyId, phoneNum);
		if (ServiceReturnUtils.isSuccess(returnInfo)) {
			if (returnInfo.getData() == null) {
				return ReturnUtils.error(ReturnCodes.PHONENUM_OR_PASSWORD_ERROR);
			}
			merchantUserBo = (EndMerchantUserBo) returnInfo.getData();
		}

		String md5NewPassword = DigestUtils.md5Hex(password);
		merchantUserBo.setPassword(md5NewPassword);

		returnInfo = endMerchantUserService.updatePassword(merchantUserBo);
		if (ServiceReturnUtils.isSuccess(returnInfo)) {
			int updated = (int) returnInfo.getData();
			if (updated > 0) {
				return ReturnUtils.success();
			}
		}
		return ReturnUtils.error(ReturnCodes.PASSWORD_RESET_FAILED);
	}

	@Override
	public RtnInfo sendSms(long companyId, String phoneNum) {
		RtnInfo rtnInfo = validator.validatePhoneNum(phoneNum);
		if (ReturnUtils.isError(rtnInfo)) {
			return rtnInfo;
		}

		ServiceReturnInfo result = endMerchantUserService.getEndMerchantUserByPhoneNum(companyId, phoneNum);
		EndMerchantUserBo bo = null;
		if (ServiceReturnUtils.isSuccess(result)) {
			bo = (EndMerchantUserBo) result.getData();
		} else {
			return ReturnUtils.error(ReturnCodes.SYSTEM_EXCEPTION);
		}
		if (bo == null) {
			return ReturnUtils.error(ReturnCodes.REGISTER_USER_NO_EXIST);
		}

		// 防刷策略（验证码未过期只能发送一次，一天5次）
		ServiceReturnInfo serviceReturnInfo = MerchantsmsSendLogService.countByPhoneNumWithDay(companyId, phoneNum);
		int count = 0;
		if (ServiceReturnUtils.isSuccess(serviceReturnInfo)) {
			count = (int) serviceReturnInfo.getData();
		} else {
			return ReturnUtils.error(ReturnCodes.SYSTEM_EXCEPTION);
		}

		if (count > AppConfig.VERIFYCODE_SEND_LIMIT) {
			return ReturnUtils.error(ReturnCodes.VERIFYCODE_SEND_LIMIT_REACHED);
		}

		String verifycodeKey = String.format(AppConfig.VERIFYCODE_KEY, companyId, phoneNum);
		if (CacheUtil.exists(verifycodeKey)) {
			VerifyCode verifyCode = JsonUtils.jsonToBean(CacheUtil.getex(verifycodeKey), VerifyCode.class);
			int diffMinutes = DateUtils.getDiffMinutes(verifyCode.getCreateTime());
			if (diffMinutes < 1) {
				// 1分钟内重复发送，提示发送频繁
				return ReturnUtils.error(ReturnCodes.VERIFYCODE_SEND_FREQUENTLY);
			}
		}

		VerifyCode verifyCode = new VerifyCode().randomCode();
		Boolean successed = smsSender.sendMsg(phoneNum, verifyCode.getValue());
		if (successed) {
			// 将验证码设置到缓存， 1分钟有效期
			CacheUtil.setex(verifycodeKey, AppConfig.EXPIRE_VERIFYCODE_MINUTE_5, verifyCode);

			SmsSendLogBo smsSendLogBo = new SmsSendLogBo();
			Date date = new Date();
			String sendDay = DateUtils.formateDate(date);
			smsSendLogBo.setCompanyId(companyId);
			smsSendLogBo.setPhoneNum(phoneNum);
			smsSendLogBo.setContent(verifyCode.getValue());
			smsSendLogBo.setSendDay(sendDay);
			smsSendLogBo.setType(DbConstants.SMS_TYPE_VERIFYCODE);
			ServiceReturnInfo returnInfo = MerchantsmsSendLogService.createSmsSendLog(smsSendLogBo);
			if (ServiceReturnUtils.isError(returnInfo)) {
				return ReturnUtils.error(ReturnCodes.SYSTEM_EXCEPTION);
			}
			return ReturnUtils.success();
		} else {
			return ReturnUtils.error(ReturnCodes.VERIFYCODE_SEND_FAILED);
		}

	}

	@Override
	public RtnInfo register(long companyId, String phoneNum, String verifyCode, String password) {
		try {
			password = RSAUtils.decryptStr(password);
		} catch (Exception e) {
			return ReturnUtils.error(ReturnCodes.PASSWORD_DECRYPT_ERROR);
		}

		RtnInfo rtnInfo = validator.validPhoneWithPassword(phoneNum, password);
		if (ReturnUtils.isError(rtnInfo)) {
			return rtnInfo;
		}

		VerifyCode verifyCodeObj = null;
		String verifycodeKey = String.format(AppConfig.VERIFYCODE_KEY, companyId, phoneNum);
		if (CacheUtil.exists(verifycodeKey)) {
			verifyCodeObj = JsonUtils.jsonToBean(CacheUtil.getex(verifycodeKey), VerifyCode.class);
		}

		if (verifyCodeObj == null || !StringUtils.equals(verifyCode, verifyCodeObj.getValue())) {
			return ReturnUtils.error(ReturnCodes.REGISTER_VERIFYCODE_ERROR);
		} else {
			CacheUtil.del(verifycodeKey);
		}

		ServiceReturnInfo returnInfo = endMerchantUserService.getEndMerchantUserByPhoneNum(companyId, phoneNum);
		if (ServiceReturnUtils.isSuccess(returnInfo)) {
			if (returnInfo.getData() != null) {
				EndMerchantUserBo merchantUserBo = (EndMerchantUserBo) returnInfo.getData();
				if (StringUtils.isBlank(merchantUserBo.getPassword())) {
					// 用户已存在但密码为空
					return this.resetPassword(companyId, phoneNum, verifyCodeObj.getValue(), password);
				}
				return ReturnUtils.error(ReturnCodes.REGISTER_USER_EXIST);
			}

		} else {
			return ReturnUtils.error(ReturnCodes.SYSTEM_EXCEPTION);
		}

		EndMerchantUserBo merchantUserBo = new EndMerchantUserBo();
		merchantUserBo.setCompanyId(companyId);
		merchantUserBo.setPhoneNum(phoneNum);

		String pwd = DigestUtils.md5Hex(password);
		merchantUserBo.setPassword(pwd);

		ServiceReturnInfo serviceReturnInfo = endMerchantUserService.createEndMerchantUser(merchantUserBo);
		if (ServiceReturnUtils.isError(serviceReturnInfo)) {
			return ReturnUtils.error(ReturnCodes.USER_CREATE_ERROR);
		}
		return ReturnUtils.success();
	}

	@Override
	public RtnInfo loginWithVerifyCode(long companyId, String phoneNum, String verifyCode) {
		RtnInfo rtnInfo = validator.validPhoneWithVerifyCode(phoneNum, verifyCode);
		if (ReturnUtils.isError(rtnInfo)) {
			return rtnInfo;
		}

		VerifyCode verifyCodeObj = null;
		String verifycodeKey = String.format(AppConfig.VERIFYCODE_KEY, companyId, phoneNum);
		if (CacheUtil.exists(verifycodeKey)) {
			verifyCodeObj = JsonUtils.jsonToBean(CacheUtil.getex(verifycodeKey), VerifyCode.class);
		}
		if (verifyCodeObj == null || !StringUtils.equals(verifyCode, verifyCodeObj.getValue())) {
			return ReturnUtils.error(ReturnCodes.VERIFYCODE_ERROR);
		} else {
			CacheUtil.del(verifycodeKey);
		}

		EndMerchantUserBo merchantUserBo = null;
		ServiceReturnInfo returnInfo = endMerchantUserService.getEndMerchantUserByPhoneNum(companyId, phoneNum);
		if (ServiceReturnUtils.isSuccess(returnInfo)) {
			if (returnInfo.getData() != null) {
				merchantUserBo = (EndMerchantUserBo) returnInfo.getData();
			}
		} else {
			return ReturnUtils.error(ReturnCodes.SYSTEM_EXCEPTION);
		}

		if (merchantUserBo == null) {
			// 用户不存在，新建用户
			merchantUserBo = new EndMerchantUserBo();
			merchantUserBo.setCompanyId(companyId);
			merchantUserBo.setPhoneNum(phoneNum);
			// 设置密码为空
			merchantUserBo.setPassword("");
			ServiceReturnInfo serviceReturnInfo = endMerchantUserService.createEndMerchantUser(merchantUserBo);
			if (ServiceReturnUtils.isError(serviceReturnInfo)) {
				return ReturnUtils.error(ReturnCodes.USER_CREATE_ERROR);
			}
		} else {
			merchantUserBo = (EndMerchantUserBo) returnInfo.getData();
		}

		Map<String, Object> resultMap = generateTokens(merchantUserBo);
		return ReturnUtils.success(resultMap);

	}

	@Override
	public RtnInfo checkVerifyCode(long companyId, String phoneNum, String verifyCode) {
		RtnInfo rtnInfo = validator.validPhoneWithVerifyCode(phoneNum, verifyCode);
		if (ReturnUtils.isError(rtnInfo)) {
			return rtnInfo;
		}

		VerifyCode verifyCodeObj = null;
		String verifycodeKey = String.format(AppConfig.VERIFYCODE_KEY, companyId, phoneNum);
		if (CacheUtil.exists(verifycodeKey)) {
			verifyCodeObj = JsonUtils.jsonToBean(CacheUtil.getex(verifycodeKey), VerifyCode.class);
		}

		if (verifyCodeObj != null && verifyCode.equals(verifyCodeObj.getValue())) {
			CacheUtil.del(verifycodeKey);
			return ReturnUtils.success();
		} else {
			return ReturnUtils.error(ReturnCodes.VERIFYCODE_ERROR);
		}
	}

	// 生成userToken和autoUserToken保存到redis
	private Map<String, Object> generateTokens(EndMerchantUserBo merchantUserBo) {
		Date currentDate = new Date();

		// 更新用户最后登录日期
		merchantUserBo.setAdminUserLastLoginDate(currentDate);
		endMerchantUserService.updateByPrimaryKey(merchantUserBo);

		// 生成userToken保存在redis中
		String UserToken = UUidUtils.getUUID();
		String tokenKey = String.format(AppConfig.MERCHANTUSERTOKEN_KEY, UserToken);
		// endMerchantUserBo.setLastActiveDate(currentDate);
		CacheUtil.setex(tokenKey, AppConfig.EXPIRE_MERCHANTUSERTOKEN_MINUTE_60, merchantUserBo);

		// 生成auto userToken保存到DB
		MerchantUserAutoLoginBo merchantUserAutoLoginBo = null;
		ServiceReturnInfo serviceReturnInfo = merchantUserAutoLoginService
				.getMerchantUserAutoLoginByEndUserId(merchantUserBo.getId());
		if (ServiceReturnUtils.isSuccess(serviceReturnInfo)) {
			if (serviceReturnInfo.getData() != null) {
				merchantUserAutoLoginBo = (MerchantUserAutoLoginBo) serviceReturnInfo.getData();
			}
		}

		String autoUserToken = "";
		if (merchantUserAutoLoginBo == null) {
			autoUserToken = UUidUtils.getUUID();
			MerchantUserAutoLoginBo userAutoLoginBo = new MerchantUserAutoLoginBo();
			userAutoLoginBo.setCompanyId(merchantUserBo.getCompanyId());
			userAutoLoginBo.setAdminUserId(merchantUserBo.getId());
			userAutoLoginBo.setAut(autoUserToken);
			userAutoLoginBo.setCreateTime(currentDate);
			// auto userToken 过期时间为15天
			Date expireTime = DateUtils.addDays(currentDate, AppConfig.EXPIRE_AUTO_MERCHANTUSERTOKEN_DAY_15);
			userAutoLoginBo.setExpireTime(expireTime);

			merchantUserAutoLoginService.createMerchantUserAutoLogin(userAutoLoginBo);

		} else {
			autoUserToken = merchantUserAutoLoginBo.getAut();
		}
		Map<String, Object> resultMap = new HashMap<String, Object>();
		resultMap.put("userToken", UserToken);
		resultMap.put("autoUserToken", autoUserToken);
		return resultMap;
	}

}
